﻿using System;
using System.Collections.Generic;
using System.IO;

namespace ReferenceSwap
{
    public class SolutionData : IDisposable // making this idisposable is ... eh...
    {
        List<string> fileLines;
        bool hasChanges;

        public SolutionData(string filePath)
        {
            Guard.Against<ArgumentException>(string.IsNullOrEmpty(filePath), "FilePath must have a valid value.");
            Guard.Against<FileNotFoundException>(!File.Exists(filePath), string.Format("Unable to locate solution file {0}.", filePath));

            hasChanges = false;
            solutionFile = new FileInfo(filePath);

            fileLines = new List<string>();
            using (StreamReader reader = new StreamReader(solutionFile.FullName))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                    fileLines.Add(line);
            }

            Parse();
        }

        #region Properties
        private FileInfo solutionFile;
        public FileInfo SolutionFile
        {
            get { return solutionFile; }
        }

        private List<ProjectReference> projectReferences;
        public List<ProjectReference> ProjectReferences
        {
            get
            {
                if (projectReferences == null)
                    projectReferences = new List<ProjectReference>();
                return projectReferences;
            }
        }

        #endregion

        public void Save()
        {
            if (!hasChanges) return;

            using (StreamWriter writer = new StreamWriter(SolutionFile.FullName))
            {
                foreach (string line in fileLines)
                {
                    if(line.Trim() != string.Empty)
                        writer.WriteLine(line);
                }
            }
        }

        public void RemoveProjectReference(ProjectReference reference)
        {
            Guard.Against<ArgumentNullException>(reference == null, "reference");

            for (int i = 0; i < fileLines.Count; i++)
            {
                if (fileLines[i].Contains(reference.Guid.ToUpper()))
                {
                    hasChanges = true;

                    if (fileLines[i].StartsWith("Project"))
                    {
                        bool done = false;
                        while (i < fileLines.Count && !done)
                        {
                            done = fileLines[i].StartsWith("EndProject");
                            fileLines.RemoveAt(i);
                        }
                    }
                    else
                        // this is a build config line
                        fileLines.RemoveAt(i); 
                }
            }

            Parse();
        }

        private void Parse()
        {
            ProjectReferences.Clear();

            // only need project references
            foreach (string line in fileLines)
            {
                if (line.StartsWith("Project"))
                    ProjectReferences.Add(ParseSolutionProjectLine(line));                
            }

            // todo: parse other data?
        }

        private ProjectReference ParseSolutionProjectLine(string line)
        {
            ProjectReference reference = new ProjectReference();
            string[] tokens = line.Split('=')[1].Split(','); // questionable...

            reference.Name = tokens[0].Replace("\"", "").Trim();
            reference.Path = tokens[1].Replace("\"", "").Trim();
            reference.Guid = tokens[2].Replace("\"", "").Trim();

            return reference;
        }

        #region IDisposable Members

        public void Dispose()
        {
            Save();
        }

        #endregion
    }
}
